﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ExtEasy;
using Ajax;
using ExtEasy.Base;
using System.Reflection;
using System.Runtime.Remoting.Contexts;
using System.Resources;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections.Specialized;
using System.Configuration;

namespace ExtEasy.Base
{   
    /// <summary>
    /// Базовый класс для странички
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class AbstractAjaxPage<T> : System.Web.UI.Page where T: ExtModel,new()
    {
        /// <summary>
        /// Список способов как хранить объектную модель на сервере
        /// </summary>
        public ModelStoreStrategy ModelStoreStrategy
        {
            get { return (ModelStoreStrategy)Enum.Parse(typeof(ModelStoreStrategy), ConfigurationManager.AppSettings["ModelStoreStrategy"]); }
        }

        /// <summary>
        /// Список способов как получать айдишник объектной модели
        /// </summary>
        public ModelIDStrategy ModelIDStrategy
        {
            get { return (ModelIDStrategy)Enum.Parse(typeof(ModelIDStrategy), ConfigurationManager.AppSettings["ModelIDStrategy"]); }
        }

        /// <summary>
        /// Объектная мдель пользователя. При запросе хирая логика - быстро добавлям новую модль если такой ещ не существует.
        /// </summary>
        public T UserObjectModel 
        {
            get
            {
                string id = ModelID;
                if (string.IsNullOrEmpty(id)) throw new Exception("Не задан ID объектной модели!");                
                T om = GetModel(id);               
                om.RefreshDate();
                return om;
            }
        }

        /// <summary>
        /// Запрос модели из хранилища. При необходимости перегрузить.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T GetModel(string id)
        {
            T om = null;
            switch (ModelStoreStrategy)
            {
                case ModelStoreStrategy.SaticRoot: om = ExtRoot.ModelsList[id] as T; break;
                case ModelStoreStrategy.ServerSession: om = ExtContext.Session[id] as T; break;
                default: throw new Exception("Не реализован способ хранения объектных моделей " + ModelStoreStrategy.ToString());
            }
            if (om == null)// throw new Exception(string.Format("Не найдена объектная модель с ID={0}!", id));
            {
                om = new T();
                om.Init(id);
                SetModel(id, om);
            }
            return om;
        }

        /// <summary>
        /// Запись модели в хранилище. При необходимости перегрузить.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="model"></param>
        public virtual void SetModel(string id, T model)
        {
            switch (ModelStoreStrategy)
            {
                case ModelStoreStrategy.SaticRoot: ExtRoot.ModelsList[id] = model; break;
                case ModelStoreStrategy.ServerSession: ExtContext.Session[id] = model; break;
                default: throw new Exception("Не реализован способ хранения объектных моделей " + ModelStoreStrategy.ToString());
            }
        }       
       
        /// <summary>
        /// Как получать айдишник пользователя. При необходимости перегрузить.
        /// </summary>
        public virtual string ModelID
        {
            get 
            {
                switch (ModelIDStrategy)
                {
                    case ModelIDStrategy.AnonymousID: return ExtContext.Request.AnonymousID;
                    case ModelIDStrategy.IdentityName: return ExtContext.User.Identity.Name;
                    case ModelIDStrategy.Login_N_IP:
                        string userName = ExtContext.User.Identity.Name;
                        if (userName.Contains("\\"))
                        {
                            userName = userName.Substring(userName.LastIndexOf("\\") + 1);
                        }
                        return userName + "_" + ExtContext.Request.UserHostAddress.Replace('.','_'); 
                    default: return ExtContext.Request.AnonymousID;
                }                
            }             
        }               

        ///// <summary>
        ///// Не забыть сказать "new" когда напишем свой Page_Load. А так же вызвать его у базового класса. Пример использования рендера в литерал-контроле:
        ///// ExtModel p = UserObjectModel;
        ///// if (IsPostBack)
        ///// {
        /////    Literal1.Text = p.FullHTML;
        ///// }
        ///// else
        ///// {
        /////     Literal1.Text = p.Render();
        ///// }
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //protected void Page_Load(object sender, EventArgs e)
        //{
        //    ExtContext = HttpContext.Current;

        //    if (IsCallback) return;

        //    Utility.RegisterTypeForAjax(this.GetType().BaseType);           
        //    Utility.RegisterTypeForAjax(typeof(ExtAjaxRes));            
            
        //    ClientScriptManager csmanager = this.ClientScript;
        //    if (!csmanager.IsClientScriptIncludeRegistered("ExtResult"))
        //    {
        //        //csmanager.RegisterClientScriptBlock(GetType(), "ExtResult", "<script type=\"text/javascript\">" + ExtResource.ExtResult.Replace("/*PageClassName*/", "=" + this.GetType().BaseType.Name) + "</script>");
        //       // csmanager.RegisterClientScriptInclude(/*this.GetType().BaseType.Name*/"JQuery", "JSHandler.ashx?resname=jquery_1_4_2");
        //        csmanager.RegisterClientScriptInclude(/*this.GetType().BaseType.Name*/"ExtResult", "JSHandler.ashx?pagename=" + this.GetType().BaseType.Name);
        //        csmanager.RegisterClientScriptInclude(/*this.GetType().BaseType.Name*/"ExtControls", "JSHandler.ashx?resname=ExtControls");
               
        //    }

        //    HtmlLink link = new HtmlLink();
        //    link.Attributes.Add("href", ExtUtils.GetAbsolutePath()+"csshandler.ashx?cssname=ExtStylesheet");
        //    link.Attributes.Add("type", "text/css");
        //    link.Attributes.Add("rel", "stylesheet");
           
        //    this.Header.Controls.AddAt(0, link);

        //    string sInclude = ExtUtils.GetAbsolutePath() + "JSHandler.ashx?resname=jquery_1_4_2";
        //   // sInclude = ResolveUrl(sInclude);
        //    HtmlGenericControl Include = new HtmlGenericControl("script");
        //    Include.Attributes.Add("type", "text/javascript");
        //    Include.Attributes.Add("src", sInclude);
        //    this.Header.Controls.AddAt(0,Include);

        //    HtmlGenericControl Include2 = new HtmlGenericControl("script");
        //    Include2.Attributes.Add("type", "text/javascript");
        //    Include2.Attributes.Add("src", ExtUtils.GetAbsolutePath() + "JSHandler.ashx?pagename=" + this.GetType().BaseType.Name);
        //    this.Header.Controls.AddAt(0, Include2);

        //    HtmlGenericControl abspathinclude = new HtmlGenericControl("script");
        //    abspathinclude.InnerHtml = "absolutePath = '" + ResolveUrl("~/") + "';";
        //    this.Header.Controls.AddAt(0, abspathinclude);
        //    //csmanager.RegisterClientScriptBlock(GetType(), GetType().ToString(), "<script type=\"text/javascript\" src=\"/ajax/ExtApp.DrugNDropPage,ExtApp.ashx\"></script>");
        //}

        public HttpContext ExtContext = HttpContext.Current;
        
        //Бля. Тогда пэйджлоад не вызывается у пэйджев-наследников
        //public override void ProcessRequest(HttpContext context)
        //{
           
        //    ExtContext = context;
        //}

        public void ProcessRequestWithContext(HttpContext context)
        {
            ExtContext = context;
            try
            {
                //string method = context.Request.Form["method"];
                string ctrlkey = context.Request.Form["ctrlkey"];
                ExtAjaxRes res = null;
                //res = GetResultWithParams(method, context.Request.Form);
                res = GetControlResult(ctrlkey, context.Request.Form);
                var path = ResolveUrl("~/");
                StringBuilder stb = new StringBuilder();
                Ajax.JSON.DefaultConverter.ToJSON(ref stb, res);
                context.Response.Write(stb.ToString());
            }
            catch (Exception ex)
            {
                context.Response.Write(ex.Message);
            }
        }

        public ExtAjaxRes GetControlResult(string ctrlkey, NameValueCollection param)
        {
            ExtAjaxRes res = new ExtAjaxRes();
            T om = UserObjectModel;
            try
            {
                res.ID = om.ID;
                res = om.ProcessControlOperation(ctrlkey, param);
                om.IsSuccess = true;
            }
            catch (Exception ex)
            {
                res.HasErrors = true;
                res.ErrorMessage = ex.InnerException == null ? ex.Message : ex.InnerException.Message;
                //string[] split = res.ErrorMessage.Split('$');
                //if (split.Length > 2) res.ErrorMessage = split[1];
                om.IsSuccess = false;
            }
            return res;
        }     

        public ExtAjaxRes GetResultWithParams(string method, object param)
        {
            ExtAjaxRes res = new ExtAjaxRes();
            T om = UserObjectModel;
            try
            {
                res.ID = om.ID;// по умолчанию обновляем все.               
                MethodInfo m = om.GetType().GetMethod(method);
                if (m == null) throw new Exception("Не реализован метод " + method);

                om.LastMethodInfo = m;
                om.LastParams = param.ToString();

                object[] p = new object[1];
                p[0] = param;
                object res2 = m.Invoke(om, p);
                if (res2 is ExtAjaxRes)
                {
                    //Если метод вернул объект типа ExtAjaxRes то возвращаем его
                    res = res2 as ExtAjaxRes;
                }
                else
                {
                    //Иначе генерим свой и обновляем все.
                    om.Render();
                    res.HTML = om.HTML;
                    res.HasErrors = false;
                }
                om.IsSuccess = true;

            }
            catch (Exception ex)
            {
                res.HasErrors = true;
                res.ErrorMessage = ex.InnerException == null ? ex.Message : ex.InnerException.Message;
                //string[] split = res.ErrorMessage.Split('$');
                //if (split.Length > 2) res.ErrorMessage = split[1];
                om.IsSuccess = false;
            }
            return res;
        }        

        public static T GetControlParent(ExtControl c)
        {
            return c.Parent as T;
        }
    }    
}
